﻿
using CPRMulti.Tools;
using HHHFramework;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using UnityEngine;
using VRCPRServer.WLan;

public class PadClientMessageController : MonoSingleton<PadClientMessageController>
{

    float reconnectionMaxTime =5f;
    float reconnectionNowTime =0f;
    float connectionMaxTime = 5f;
    float connectionTime = 0;
    bool IsConcentServer = false;
    bool isFirstConcent = false;
    private Thread thread;
    #region 接受数据 deleget

    //硬件状态
    public Action deviceReady;
    public Action deviceNotReady;
    public bool deviceisReady = false;

    //操作数据
    public Action showOperationMessageAction;
    public Action hideOperationMessageAction;
    public bool isShowOperationInfo = false;

    /// <summary>
    /// 显示局部视角
    /// </summary>
    public Action showDetailViewMessageAction;
    /// <summary>
    /// 隐藏局部视角
    /// </summary>
    public Action hideDetailViewMessageAction;
    public bool isShowDetailView =false;

    //生命信号
    public Action showVitalsignsMessageAction;
    public Action hideVitalsignsMessageAction;
    public Action reciveMessageShowTeachCPR;
    public Action reciveMessageHideTeachCPR;

    public bool isShowVitalsigns =false;
    ClientManager clientManager;
    #endregion

    private void Start()
    {

    }
    private void CreateManager() {
       clientManager = new ClientManager();

    }


    private void Update()
    {
        if(clientManager!=null){
            if (clientManager.tcpClient==null) { return; }
            if (clientManager.tcpClient.IsConnected)
            {
                connectionTime += Time.deltaTime;
                if (connectionTime > connectionMaxTime)
                {
                    clientManager.tcpClient.Dispose();
                    connectionTime = 0;
                }
                if (clientManager.dataBuffer.DataCount==0) { return; }
                ReciveMessage();
                reconnectionNowTime = 0;
            }
            else
            {
                reconnectionNowTime += Time.unscaledDeltaTime;
                if (reconnectionNowTime > reconnectionMaxTime)
                {
                    clientManager.tcpClient.Dispose();
                    CreatAndConnect();
                    reconnectionNowTime = 0;                   
                }
            }
        }
        
    }
    public void CreatAndConnect() {
        Debug.LogError("CONNECT");

        IsConcentServer = false;
        clientManager.NewClient();
        clientManager.tcpClient.Connect();
        clientManager.SendHeart = ()=> {
            if (IsConcentServer == false) {
                Thread.Sleep(300);
                PadSendMessageToServer("IsConcentServer");
            }
        };
        thread = new Thread(new ThreadStart(ThreadTimer));
        thread.IsBackground = true;
        thread.Start();
    }
    #region pad 接受数据
   
    public void ReciveMessage()
    {
        if(clientManager.dataBuffer.DataCount == 0) {
            return;
        }
        else
        {
            Debug.Log("接收到了数据");
        }
        byte[] head = new byte[1];
        byte[] type = new byte[1];
        byte[] msgLength = new byte[2];
        head = clientManager.dataBuffer.ReadBuffer(1);
        if (head != null)
        {
            if (head[0] == 0xFF)
            {
                type = clientManager.dataBuffer.ReadBuffer(1);
                if (type != null)
                {
                    msgLength = clientManager.dataBuffer.ReadBuffer(2);
                    if (msgLength == null)
                    {
                        Debug.Log("msglength null");
                        return;
                    }
                    else
                    {
                        int dataLength = msgLength[0] * 256 + msgLength[1] ;
                        byte[] data = new byte[dataLength];                     
                        data = clientManager.dataBuffer.ReadBuffer(dataLength);
                        if (data != null&&dataLength!=0)
                        {
                            string step = string.Empty;
                            byte[] sumDatas = new byte[dataLength + 4];
                            sumDatas[0] = head[0];
                            sumDatas[1] = type[0];
                            sumDatas[2] = msgLength[0];
                            sumDatas[3] = msgLength[1];
                            data.CopyTo(sumDatas, 4);
                            byte sum = Sum1(sumDatas, 0, sumDatas.Length - 1);
                            Debug.Log("获取数据dataLength" + dataLength);
                            if (sum == data[dataLength - 1])
                            {
                                Debug.Log("校验成功");
                                MessageCheck(type[0], data);
                            }

                        }
                    }
                }
            }
            else { Debug.Log("type null"); }

        }
        else { Debug.Log(" data null"); }
    }

    private void MessageCheck(byte type, byte[] data)
    {
        data = data.Take(data.Length - 1).ToArray();

        if (type == CommandType.connected)
        {            
            if (Enumerable.SequenceEqual(data, CommandData.isConcentServer))
            {
                Debug.Log("连接成功");
                IsConcentServer = true;
                //UIManager.GetInstance().ShowUIForms("SceneChooseUIForm");//做到重连状态同步后删掉这个命令
                PadSendMessageToServer("Reconnection");
            }
            if (Enumerable.SequenceEqual(data, CommandData.heartData))
            {
                Debug.Log("接收到心跳包");
                connectionTime = 0;
            }

        }

        if (type == CommandType.padTouchCommand)
        {
            if (Enumerable.SequenceEqual(data, CommandData.showOperation))
            {
                isShowOperationInfo = true;
                showOperationMessageAction?.Invoke();
                Debug.Log("message operation");
            }
            if (Enumerable.SequenceEqual(data, CommandData.hideOperation))
            {
                isShowOperationInfo = false;
                hideOperationMessageAction?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.showPartial))
            {
                isShowDetailView = true;
                showDetailViewMessageAction?.Invoke();
                Debug.Log("message detailview");
            }
            if (Enumerable.SequenceEqual(data, CommandData.hidePartial))
            {
                isShowDetailView = false;
                hideDetailViewMessageAction?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.showVitalSigns))
            {
                isShowVitalsigns = true;
                showVitalsignsMessageAction?.Invoke();
                Debug.Log("message Vitalsigns");
            }
            if (Enumerable.SequenceEqual(data, CommandData.hideVitalSigns))
            {
                isShowVitalsigns = false;
                hideVitalsignsMessageAction?.Invoke();
            }
        }

        
        if (type == CommandType.pcReturn)
        {
            if (Enumerable.SequenceEqual(data, CommandData.deviceReady))
            {
                deviceisReady = true;
                deviceReady?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.deviceNotReady))
            {
                deviceisReady = false;
                deviceNotReady?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.choosePanel))
            {
                //UIManager.GetInstance().ShowUIFormHideOther("SceneChooseUIForm");

                hideDetailViewMessageAction?.Invoke();
                isShowDetailView = false;

                isShowOperationInfo = false;
                hideOperationMessageAction?.Invoke();

                isShowVitalsigns = false;
                hideVitalsignsMessageAction?.Invoke();
            }

            if (Enumerable.SequenceEqual(data, CommandData.scenePanel))
            {
                //UIManager.GetInstance().ShowUIFormHideOther("ScenePanelUIForm");
            }

            if (Enumerable.SequenceEqual(data, CommandData.showTeachCPR))
            {
                Debug.LogError("show teach CPR");
                reciveMessageShowTeachCPR?.Invoke();
            }
            if (Enumerable.SequenceEqual(data, CommandData.HideTeachCPR))
            {
                Debug.LogError("hide teach CPR");
                reciveMessageHideTeachCPR?.Invoke();
            }

        }

    }

    #endregion
    #region pad 发送数据
    public void PadSendMessageToServer(string sendName)
    {
        byte[] data = new byte[9];
        #region
        switch (sendName)
        {
            #region main
            case "Heart":
                {
                    data = SetSendStringMessage(CommandType.connected, CommandData.heartData);
                }
                break;


            case "IsConcentServer":
                {
                    //在这里返回连接请求等待服务器返回相同的数据
                    data = SetSendStringMessage(CommandType.connected, CommandData.isConcentServer);
                }
                break;
            case "IsDisconcentServer":
                {
                    data = SetSendStringMessage(CommandType.connected, CommandData.isDisConcentServer);
                }
                break;

            case "Reconnection":
                {
                    data = SetSendStringMessage(CommandType.connected, CommandData.reconnection);
                }
                break;

            #endregion

            #region scenePanel
            case "Back":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.back);
                }
                break;
            case "ShowOperation"://显示操作数据
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.showOperation);
                }
                break;
            case "HideOperation"://隐藏操作数据
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.hideOperation);
                }
                break;
            case "ShowVitalSigns"://显示生命体征
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.showVitalSigns);
                }
                break;
            case "HideVitalSigns"://隐藏生命体征
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.hideVitalSigns);
                }
                break;

            case "ShowPartial"://显示局部视角
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.showPartial);
                }
                break;
            case "HidePartial"://隐藏局部视角
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.hidePartial);
                }
                break;
            case "Start":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.startData);
                }
                break;
            case "Pause":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.pauseData);
                }
                break;

            case "Skip":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.skipData);
                }
                break;
            case "AED":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.aedData);
                }
                break;
            case "120":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.data120);
                }
                break;
            case "播放教学视频":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.teachingCPRPlay);
                }
                break;

            #endregion

            #region  sceneChoose
            case "预览地铁场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.previewSubwayScene);
                }
                break;
            case "预览火灾场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.previewFireScene);
                }
                break;
            case "预览溺水场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.previewDrowningScene);
                }
                break;
            case "预览地震场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.previewEarthquakeScene);
                }
                break;
            case "预览车祸场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.previewTrafficAccidentScene);
                }
                break;
            
            case "打开地铁场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.openSubwayScene);
                }
                break;
            case "打开火灾场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.openFireScene);
                }
                break;
            case "打开溺水场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.openDrowningScene);
                }
                break;
            case "打开地震场景":
                {

                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.openEarthquakeScene);
                }
                break;
            case "打开车祸场景":
                {
                    data = SetSendStringMessage(CommandType.padTouchCommand, CommandData.openTrafficAccidentScene);
                }
                break;         
            #endregion

            default:

                Debug.LogError("出现未识别指令：" + sendName + "返回");
                return;
        }
        #endregion
        clientManager.tcpClient.Send(data);
        data = null;
    }

    private byte[] SetSendStringMessage(byte order, byte[] msg)
    {
        byte[] data = new byte[9];
        data[0] = 0xFF;
        data[1] = order;
        data[2] = 0x00;
        data[3] = 0x05;
        data[4] = msg[0];
        data[5] = msg[1];
        data[6] = msg[2];
        data[7] = msg[3];
        data[8] = Sum1(data, 0, 9);
        return data;
    }

    public void PadSendMessageToServer<T>(T classInfo,byte comTpe) {
        var data = SetSendClassMessage(classInfo,comTpe);
        clientManager.tcpClient.Send(data);
    }

    //private byte[] SetSendModelConnectMessage(ModelInfo modelInfo)
    //{
    //    if (modelInfo == null) return null;

    //    byte[] bytes = SerializeObject.SerializeToBytes(modelInfo);
    //    Debug.Log("length:"+bytes.Length);
    //    if (bytes == null) return null;
    //    int length = bytes.Length + 5;
    //    int dataLength = bytes.Length + 1;

    //    byte[] datas = new byte[length];
    //    datas[0] = 0XFF;
    //    datas[1] = CommandType.modelConnectInfo;
    //    datas[2] = (byte)(dataLength >> 8);
    //    datas[3] = (byte)(dataLength & 0xff);
    //    Array.Copy(bytes, 0, datas, 4, bytes.Length);
    //    datas[length - 1] = datas.Sum1(0, length - 1);
    //    return datas;
    //}
    private byte[] SetSendClassMessage<T>(T classT, byte commandTYpe) {
        if (classT == null) return null;

        byte[] bytes = SerializeObject.SerializeToBytes(classT);
        Debug.Log("length:" + bytes.Length);
        if (bytes == null) return null;
        int length = bytes.Length + 5;
        int dataLength = bytes.Length + 1;

        byte[] datas = new byte[length];
        datas[0] = 0XFF;
        datas[1] = commandTYpe;
        datas[2] = (byte)(dataLength >> 8);
        datas[3] = (byte)(dataLength & 0xff);
        Array.Copy(bytes, 0, datas, 4, bytes.Length);
        datas[length - 1] = datas.Sum1(0, length - 1);
        return datas;
    }



    #endregion

    #region  网络
    void WlanConnected() {
        if (!WlanHelper.IsConnectedInternet()) {
            //在这里打开选择网络的界面
        }
       
    }
    #endregion
    private void OnApplicationQuit()
    {
        PadSendMessageToServer("IsDisconcentServer");
        clientManager.DisPose();
    }

    public static byte Sum1(byte[] bytes, int start, int length)
    {
        byte sum = 0;
        int endIndex = start + length;

        if (bytes == null || bytes.Length < 1)
            new NullReferenceException("bytes is null or bytes length < 1");

        if (start > bytes.Length || endIndex > bytes.Length)
            new IndexOutOfRangeException("bytes Index OutOf Range");

        for (int i = start; i < endIndex; i++)
            sum += bytes[i];

        return sum;
    }
    #region 心跳

    private DateTime heartTime = DateTime.Now;

    private void ThreadTimer()
    {
        while (true)
        {
            if (Math.Abs(DateTime.Now.Second - heartTime.Second) >= 0.9)
            {
                heartTime = DateTime.Now;
                PadSendMessageToServer("Heart");

            }
            Thread.Sleep(1);
        }
    }
    #endregion

}
public class CommandType
{
    /// <summary>
    /// 类型 模拟人连接信息
    /// </summary>
    public static readonly byte modelConnectInfo = 0xFA;

    /// <summary>
    /// 类型 pad操作指令
    /// </summary>
    public static readonly byte padTouchCommand = 0xFB;
    /// <summary>
    /// 类型 按压操作数据设置
    /// </summary>
    public static readonly byte cprDataSet = 0xFC;
    /// <summary>
    /// 连接状态
    /// </summary>
    public static readonly byte connected = 0xFD;

    public static readonly byte pcReturn = 0xFE;

    public static readonly byte teachingAudioVolume = 0xF0;
}

public class CommandData
{
    #region connected
    /// <summary>
    /// 心跳包
    /// </summary>
    public static readonly byte[] heartData = { 0x00, 0x00, 0x00, 0x00 };

    public static readonly byte[] isConcentServer = { 0x01, 0x01, 0x01, 0x01 };

    public static readonly byte[] isDisConcentServer = { 0x02, 0x02, 0x02, 0x02 };

    public static readonly byte[] reconnection = { 0x03, 0x03, 0x03, 0x03 };
    #endregion

    #region padTouch  scenePanel AX   sceneChoosePanel BX CX


    /// <summary>
    ///显示操作数据
    /// </summary>
    public static readonly byte[] showOperation = { 0xA1, 0xA1, 0xA1, 0xA1 };
    /// <summary>
    /// 隐藏操作数据
    /// </summary>
    public static readonly byte[] hideOperation = { 0xA2, 0xA2, 0xA2, 0xA2 };
    /// <summary>
    /// 显示生命体征
    /// </summary>
    public static readonly byte[] showVitalSigns = { 0xA3, 0xA3, 0xA3, 0xA3 };
    /// <summary>
    /// 隐藏生命体征
    /// </summary>
    public static readonly byte[] hideVitalSigns = { 0xA4, 0xA4, 0xA4, 0xA4 };
    /// <summary>
    /// 显示局部视角
    /// </summary>
    public static readonly byte[] showPartial = { 0xA5, 0xA5, 0xA5, 0xA5 };
    /// <summary>
    /// 隐藏局部视角
    /// </summary>
    public static readonly byte[] hidePartial = { 0xA6, 0xA6, 0xA6, 0xA6 };

    public static readonly byte[] startData = { 0xA7, 0xA7, 0xA7, 0xA7 };

    public static readonly byte[] pauseData = { 0xA8, 0xA8, 0xA8, 0xA8 };

    public static readonly byte[] back = { 0xA9, 0xA9, 0xA9, 0xA9 };

    public static readonly byte[] skipData = { 0xAA, 0xAA, 0xAA, 0xAA };

    public static readonly byte[] aedData = { 0xAB, 0xAB, 0xAB, 0xAB };

    public static readonly byte[] data120 = { 0xAC, 0xAC, 0xAC, 0xAC };

    public static readonly byte[] teachingCPRPlay = { 0xAD, 0xAD, 0xAD, 0xAD };

    public static readonly byte[] openSubwayScene = { 0xC1, 0xC1, 0xC1, 0xC1 };
    public static readonly byte[] openFireScene = { 0xC2, 0xC2, 0xC2, 0xC2 };
    public static readonly byte[] openDrowningScene = { 0xC3, 0xC3, 0xC3, 0xC3 };
    public static readonly byte[] openEarthquakeScene = { 0xC4, 0xC4, 0xC4, 0xC4 };
    public static readonly byte[] openTrafficAccidentScene = { 0xC5, 0xC5, 0xC5, 0xC5 };

    public static readonly byte[] previewSubwayScene = { 0xB1, 0xB1, 0xB1, 0xB1 };
    public static readonly byte[] previewFireScene = { 0xB2, 0xB2, 0xB2, 0xB2 };
    public static readonly byte[] previewDrowningScene = { 0xB3, 0xB3, 0xB3, 0xB3 };
    public static readonly byte[] previewEarthquakeScene = { 0xB4, 0xB4, 0xB4, 0xB4 };
    public static readonly byte[] previewTrafficAccidentScene = { 0xB5, 0xB5, 0xB5, 0xB5 };
    #endregion


    #region pc Rturn 
    public static readonly byte[] deviceNotReady = { 0xE0, 0xE0, 0xE0, 0xE0 };
    public static readonly byte[] deviceReady = { 0xE1, 0xE1, 0xE1, 0xE1 };
    public static readonly byte[] choosePanel = { 0xE2, 0xE2, 0xE2, 0xE2 };
    public static readonly byte[] scenePanel = { 0xE3, 0xE3, 0xE3, 0xE3 };
    public static readonly byte[] showTeachCPR = { 0xE4, 0xE4, 0xE4, 0xE4 };
    public static readonly byte[] HideTeachCPR = { 0xE5, 0xE5, 0xE5, 0xE5 };
    #endregion

}
[Serializable]
public class ModelInfo
{
    public string modelID;
    public bool isMainModel;
    public string ipAddress;
    public string port;
    public bool connect;
}

